/*
 * Copyright (c) 2008, 2009 Christopher Condit (condit@sdsc.edu)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/***
 * This software is an aid to processing the files distributed as part of NOAA's 
 * Global Precipitation Climatology Project (GPCP) program
 * (see http://www1.ncdc.noaa.gov/pub/data/gpcp/gpcp-v2.1/)
 * This program takes a single file from the GPCP as input and outputs an ArcInfo
 * ASCII grid file for each day as a peer to the input file. You can then use this
 * with your favorite geospatial tool to further analyze the data...
 ***/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

const int i = 1;
#define is_bigendian() ( (*(char*)&i) == 0 )

#define HEADER_SIZE 576
#define NUM_ROWS 72
#define NUM_COLS 144

/***
 * printHeader prints the ArcInfo ASCII Grid header
 * param: out - the output file
 ***/
void printHeader(FILE *out)
{
	fprintf(out, "ncols 144\nnrows 72\nxllcorner 0.0\nyllcorner -90\ncellsize 2.5\nnodata_value -99999\n");
}

int main(int argc, char* argv[])
{
	if (NULL == argv[1])
	{
		printf("Please provide an input filename...\n");
		exit(-1);
	}

	FILE *input = fopen(argv[1], "rb");
	if (!input)
	{
		printf("Failed to open: %s", argv[1]);
		exit(-1);
	}
	fseek(input, 0, SEEK_END);
	int end = ftell(input);
	fseek (input, 0, SEEK_SET);

	//Skip the header
	fseek(input, HEADER_SIZE, 0);
	//A buffer for reading input
	unsigned int buffer;
	//Iterators for grabbing individual days
	int row, col;
	//The day count
	short day = 0;

	int bytesIn = HEADER_SIZE;
	
	while (bytesIn < end)
	{
		day++;
		//Create the output file for this day of data
		char *outfilename = (char *)malloc((strlen(argv[1]) + 8) * sizeof(char));
		sprintf(outfilename, "%s%02i.asc", argv[1], day);
		FILE *outfile = fopen(outfilename, "w");
		//Add the header to the file...
		printHeader(outfile);
		for (row = 0; row < NUM_ROWS; row ++)
		{
			for (col = 0; col < NUM_COLS; col++)
			{
				//Get four bytes of data
				size_t result = fread(&buffer, sizeof(unsigned int), 1, input);			
				bytesIn += 4;				
				if (!is_bigendian())
				{	//Swap the byte order if necessary
					buffer = (buffer>>24) | 
							 ((buffer<<8) & 0x00FF0000) |
							 ((buffer>>8) & 0x0000FF00) |
							 (buffer<<24);
				}
				//Convert the value to a float
				float *fVal = (float *)&buffer;
				fprintf(outfile, "%f ", *fVal);
			}
			fprintf(outfile, "\n");
		}
		fclose(outfile);
		free(outfilename);
	}
	fclose(input);
}

